<html>
	<head>
		<link rel="stylesheet" href="./lineawesome/css/line-awesome.min.css" />
		<link rel="stylesheet" href="./speedtest.css?ver=1" />
		<meta charset="utf8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		<title>VDON Speed Test</title>
		<style>
			.fullscreen { 
				width:100%;
				height: calc(100% - 35px);
				position:absolute;
				left:0;
				display:block;
				background-color: #444;
				color:white;
				margin: auto;
				padding-top: 35px;
				transition: all ease-in 1s;
				animation-name: fadein;
				animation-duration: .3s;
			}
			
			@keyframes fadein {
			  0%   {opacity: 0.5;}
			  100% {opacity: 1;}
			}
			a {
				color: white;
			}
			#controls button {
				cursor: pointer;
				display: inline;
				padding: 20px;
			}
			.hidden {
				display:none!important;
			}
			body {
				text-align: center;
				height:unset;
				background: #444;
				font-family: 'Noto Sans', sans-serif;
				color:white;
			}
			h2 {
				width: 760px;
				max-width: 90%;
				margin: auto;
			}
			
			li {
				text-align: left;
			}
			
			button{
				margin: 50px auto;
				font-size: 120%;
				padding: 20px 30px;
				cursor:pointer;
			}
		</style>
	</head>
	<body>
		<div id="mainapp" >
			<h1>
				Video and stream quality check results
			</h1>
			<div id="container">
			</div>
			<div id="graphs">
				<div class="graph">
					<h3>Bitrate (kbps)</h3>
					<span>0</span>
					<canvas id="bitrate-graph"></canvas>
				</div>

				<div class="graph">
					<h3>Buffer delay (ms)</h3>
					<span>0</span>
					<canvas id="buffer-graph"></canvas>
				</div>

				<div class="graph">
					<h3>Packet Loss (%)</h3>
					<span>0</span>
					<canvas id="packetloss-graph"></canvas>
				</div>
			</div>
			<div id="details">
			</div>
			
		</div>

		<script>
		
			function getChromeVersion() {
				var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
				return raw ? parseInt(raw[2], 10) : false;
			}
			
			function next1(){
				document.getElementById("page1").classList.add("hidden");
				document.getElementById("page2").classList.remove("hidden");
			}
			
			function next2(){
				document.getElementById("page2").classList.add("hidden");
				document.getElementById("page3").classList.remove("hidden");
				loadIframe();
			}
			
			function next3(){
				document.getElementById("page3").classList.add("hidden");
				document.getElementById("mainapp").classList.remove("hidden");
				loadIframe();
			}
		
			(function (w) {
				w.URLSearchParams =
					w.URLSearchParams ||
					function (searchString) {
						var self = this;
						self.searchString = searchString;
						self.get = function (name) {
							var results = new RegExp("[\?&]" + name + "=([^&#]*)").exec(
								self.searchString
							);
							if (results == null) {
								return null;
							} else {
								return decodeURI(results[1]) || 0;
							}
						};
					};
			})(window);
			var urlParams = new URLSearchParams(window.location.search);
			
		
			
			function copyFunction(copyText) {
				alert("Log copied to the clipboard.");
				try {
					copyText.select();
					copyText.setSelectionRange(0, 99999);
					document.execCommand("copy");
				} catch (e) {
					var dummy = document.createElement("input");
					document.body.appendChild(dummy);
					dummy.value = copyText;
					dummy.select();
					document.execCommand("copy");
					document.body.removeChild(dummy);
					return false;
				}
				
			}
			
			function printValues(obj) {
				var out = "";
				for (var key in obj) {
					if (typeof obj[key] === "object") {
						out += "<br />";
						out += printValues(obj[key]);
					} else {
						if (key.startsWith("_")) {
						} else {
							out += "<b>" + key + "</b>: " + obj[key] + "<br />";
						}
					}
				}
				return out;
			}


			var streamID = "";
			if (urlParams.has("id")) {
				streamID = urlParams.get("id");
			}
		
			var bitrate = {
				element: "bitrate-graph",
				data: 0,
				max: 6000,
				target: 2500,
			};
			var frames;
			var buffer = {
				element: "buffer-graph",
				data: 0,
				max: 200,
				target: 100,
			};
			var packetloss = {
				element: "packetloss-graph",
				data: 0,
				max: 3,
				target: 2,
			};
			
			// https://record.vdo.workers.dev/?name="+recordResults
			
			var QLR_1 = 0;
			var QLR_2 = 0;
			var QLR_3 = 0;
			
			var BBB = 0;
			var counter = 0;
			
			var BUFF = 0;
			var BUFFCCC = 0;
			
			var PAK = 0;
			var PAKCCC = 0;
			
			function process(arr) {
				console.log(arr);
				arr.forEach(data=>{
					if ("bitrate" in data){
						updateData("bitrate", data.bitrate);
						if (data.bitrate!==null){
							BBB +=  data.bitrate;
							counter += 1;
						}
					}
					if ("target" in data){
						updateData("target", data.target);
					}
					if ("buffer" in data){
						updateData("buffer", data.buffer);
						if (data.buffer!==null){
							BUFF += data.buffer;
							BUFFCCC += 1;
						}
					}
					if ("packetloss" in data){
						updateData("packetloss", data.packetloss);
						if (data.packetloss!==null){
							PAK += parseFloat(data.packetloss) || 0;
							PAKCCC += 1;
							
						}
					}
					if ("resolution" in data){
						updateData("resolution", data.resolution);
					}
					if ("QLR" in data){
						if (data.QLR == "none"){
							QLR_1 +=1;
						} else if (data.QLR.toLowerCase() == "cpu"){
							QLR_2 +=1;
						} else if (data.QLR.toLowerCase() == "network"){
							QLR_3 +=1;
						}
					}
					if ("info" in data){
						if (data.info.Browser){
							document.getElementById("details").innerHTML += "<br /><b>Browser used:</b> "+data.info.Browser+"<br />";
							if (!data.info.Browser.startsWith("Chromium")){
								document.getElementById("details").innerHTML += "<h3>A Chromium-based browser is recommended.</h3>";
							} 
						}
						if ("plugged_in" in data.info){
							if (!data.info.plugged_in){
								document.getElementById("details").innerHTML += "<h3>The user's power is not plugged in</h3>";
							}
						}
						if (data.info.platform){
							document.getElementById("details").innerHTML += "<br /><b>Platform (os):</b> "+data.info.platform+"<br />";
						}
						if (data.info.gpGPU){
							document.getElementById("details").innerHTML += "<br /><b>GPU:</b> "+data.info.gpGPU+"<br />";
						}
						if (data.info.conn_type){
							document.getElementById("details").innerHTML += "<br /><b>Connection type:</b> "+data.info.conn_type+"<br />";
							if (data.info.conn_type == "wifi"){
								document.getElementById("details").innerHTML += "<h3>Avoid using WiFi if at all possible</h3>";
							}
							
						}
					}
				});
				// container
				
				var total = QLR_1 + QLR_2 + QLR_3;
				if (QLR_2/total>0.5){
					document.getElementById("container").innerHTML += "Serious CPU overload issues. Consider reducing the capture resolution.<br />";
				} else if (QLR_2/total>0.1){
					document.getElementById("container").innerHTML += "Occassional CPU overload issues. Consider reducing the capture resolution.<br />";
				}
				if (QLR_3/total>0.5){
					document.getElementById("container").innerHTML += "The network quality or bandwidth limited the performance.<br />";
				} else if (QLR_3/total>0.1){
					document.getElementById("container").innerHTML += "The network quality or bandwidth may have limited the performance.<br />";
				}
				
				document.getElementById("container").innerHTML += "The average bitrate was: "+parseInt(BBB/counter)+"-kbps<br />";
		
				if (BBB/counter<500){
					document.getElementById("container").innerHTML += "<h3>Bitrate is really bad</h3>";
				}
				else if (BBB/counter<1000){
					document.getElementById("container").innerHTML += "<h3>Bitrate is poor</h3>";
				}
				else if (BBB/counter<2000){
					document.getElementById("container").innerHTML += "<h3>Bitrate a bit low</h3>";
				} 
				else {
					document.getElementById("container").innerHTML += "<h3>Bitrate is good</h3>";
				}
				
				document.getElementById("container").innerHTML += "<br />The average buffer length was: "+parseInt(BUFF/BUFFCCC)+"-ms<br />";
				
				if (BUFF/BUFFCCC>500){
					document.getElementById("container").innerHTML += "<h3>Video delay is really bad</h3><br />";
				}
				else if (BUFF/BUFFCCC>200){
					document.getElementById("container").innerHTML += "<h3>Video delay is poor</h3><br />";
				}
				else if (BUFF/BUFFCCC>100){
					document.getElementById("container").innerHTML += "<h3>Video delay is sub-optimal</h3><br />";
				} 
				else {
					document.getElementById("container").innerHTML += "<h3>Video delay is good</h3><br />";
				}
				
				document.getElementById("container").innerHTML += "The average packet loss was: "+(parseInt(PAK*1000/PAKCCC)/1000.0)+"%<br />";
				
				if (PAK/PAKCCC>3){
					document.getElementById("container").innerHTML += "<h3>Packet loss is extremely bad; Must Fix This</h3>";
				}
				else if (PAK/PAKCCC>0.8){
					document.getElementById("container").innerHTML += "<h3>Packet loss is quite bad; expect problems with audio and video</h3>";
				}
				else if (PAK/PAKCCC>.15){
					document.getElementById("container").innerHTML += "<h3>Packet loss is a bit high; might be a testing-server issue though</h3>";
				} 
				else {
					document.getElementById("container").innerHTML += "<h3>Packet loss is good</h3>";
				}
				
				console.log(QLR_1, QLR_2, QLR_3);
				
			}
			
			var xmlhttp = new XMLHttpRequest();
			var url = "https://record.vdo.workers.dev/?name="+streamID;

			xmlhttp.onreadystatechange = function() {
				if (this.readyState == 4 && this.status == 200) {
					var myArr = JSON.parse(this.responseText);
					process(myArr);
				}
			};
			xmlhttp.open("GET", url, true);
			xmlhttp.send();

			
			
			function updateData(type, data) {
			
				if (type == "target"){
					bitrate.target = data;
				}
				
				if (type == "bitrate") {
					bitrate.data = data;
					plotData("bitrate", bitrate);
					plotData("bitrate", bitrate);
					plotData("bitrate", bitrate);
				}

				if (type == "buffer") {
					buffer.data = data;
					plotData("buffer", buffer);
					plotData("buffer", buffer);
					plotData("buffer", buffer);
				}

				if (type == "packetloss") {
					packetloss.data = data;
					plotData("packetloss", packetloss);
					plotData("packetloss", packetloss);
					plotData("packetloss", packetloss);
				}
			}

			function plotData(type, stat) {
				var canvas;
				var context;
				var yScale;

				canvas = document.getElementById(stat.element);
				context = canvas.getContext("2d");

				if (isNaN(stat.data)) {
					stat.data = 0;
				}

				var text = (canvas.previousElementSibling.innerHTML = stat.data);

				var height = context.canvas.height;
				var width = context.canvas.width;

				var borderWidth = 5;
				var offset = borderWidth * 2;

				// Create gradient
				var grd = context.createLinearGradient(0, 0, 0, height);

				if (type == "bitrate") {
					
					if (stat.target <= 3000){
						grd.addColorStop(0, "#33C433");
						grd.addColorStop(0.7, "#33C433");
						grd.addColorStop(0.8, "#F3F304");
						grd.addColorStop(0.92, "#F30404");
					} else if (stat.target <= 4000){
						grd.addColorStop(0, "#33C433");
						grd.addColorStop(0.5, "#33C433");
						grd.addColorStop(0.8, "#F3F304");
						grd.addColorStop(0.92, "#F30404");
					} else {
						grd.addColorStop(0, "#33C433");
						grd.addColorStop(0.3, "#33C433");
						grd.addColorStop(0.8, "#F3F304");
						grd.addColorStop(0.92, "#F30404");
					}
					
				} else {
					// Higher values are red
					grd.addColorStop(0, "#F30404");
					grd.addColorStop(0.3, "#F3F304");
					grd.addColorStop(0.7, "#33C433");
				}

				context.strokeStyle = "white";
				context.fillStyle = grd;
				//context.fillStyle = "#009933";
				//context.imageSmoothingEnabled = true;

				yScale = height / stat.max;

				if (stat.data > stat.max) {
					stat.data = stat.max;
				}

				if (type == "packetloss" && stat.data == 0.0) {
					stat.data = 0.1;
				}


				var x = width - 1;
				var y = height - stat.data * yScale;
				var w = 1;

				context.fillStyle = grd;
				context.fillRect(x, y, w, height);

				// shift everything to the left:
				var imageData = context.getImageData(1, 0, width - 1, height);
				context.putImageData(imageData, 0, 0);
				// now clear the right-most pixels:
				context.clearRect(width - 1, 0, 1, height);
			}
		</script>
	</body>
</html>
